<template>
  <el-dialog
    :modelValue="modelValue"
    @update:model-value="emits('update:modelValue', $event)"
    :title="title"
    width="700"
    id='paramedit'>
    <div>
      <div mb2>函数名</div>
      <el-input v-model="unsave.name" autocomplete="off" />

      <VarTable
        :model-value="unsave.params"
        title="参数"
        namespace="参数"
        type="PSlotin" my/>

      <VarTable
        :model-value="unsave.returns"
        title="返回值"
        namespace="返回值"
        type="PSlotout" />  
    </div>
    <div flex justify-end>
      
    </div>
    <template #footer>
      <div class="dialog-footer" flex>
        <el-button mlauto @click="emits('update:modelValue', false)">取消</el-button>
        <el-button type="primary" @click="confirm()">
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import _ from 'lodash'
import { Graph } from '~/models/graph/graph';
import { PSlot } from '~/models/graph/slot/prototype';
import { ISlot } from '~/models/graph/slot/instance';
import { tBool, tNum, TypesReceiveLiterial } from '~/models/types';
import { oProject, oStorage } from '~/models/Project';
import { PNodeType } from '~/models/graph/node/type';
import { PNode } from '~/models/graph/node/prototype';
import { Deserializer } from '~/models/serialize/Deserializer';
import { Dzer } from '~/models/serialize';

const props = defineProps<{
  modelValue: boolean,
  target?: Graph,
}>()

const unsave = ref(new Graph())

const emits = defineEmits<{
  (e: 'update:modelValue', item: boolean): void
  (e: 'confirm', item: void): void
}>()

watch(() => props.modelValue, val => {
  if (val) {
    const empty = oStorage.value!.graphs.length === 0
    const formatName = uniqueNaming("新函数", oStorage.value!.graphs.map(x => x.name))
    const newName = empty ? 'Main主函数' : formatName
    if (props.target) {
      unsave.value.name = props.target.name || newName
      unsave.value.params = Dzer.clone(props.target.params)
      unsave.value.returns = Dzer.clone(props.target.returns)
    }
    else {
      unsave.value.name = newName
      unsave.value.params = []
      unsave.value.returns = []
    }
  }
},{
  immediate: true
})

function confirm() {

  if (!oStorage.value) {
    throw "!oStorage.value"
  }

  // 修复手动输入的初始值的类型
  // unsave.value.params.forEach(param => {
  //   if (param.defaultValue !== undefined) {
  //     if (param.dataType!.is(tNum)) {
  //       param.defaultValue = parseFloat(param.defaultValue as any)
  //     }
  //     else if (param.dataType!.is(tBool)) {
  //       param.defaultValue = !!param.defaultValue
  //     }
  //     else {
  //       param.defaultValue = param.defaultValue.toString()
  //     }
  //   }
  // })

  // 传参了（修改函数签名 / 按照预设新建）
  if (props.target) {
    // 传参了，但是没挂载（按照预设新建）
    if (oStorage.value.graphs.indexOf(props.target) < 0) {
      oStorage.value.graphs.push(props.target)
    }
    // 挂载了（修改变量）
    else {
      // 这时要对(所有)图进行检查。如果有任何调用
      // 节点创建了，则需要更新节点确保正确性
      for (const graph of oStorage.value.graphs) {
        for (const node of graph.nodes) {
          const p = node.prototype
          if (p.name === props.target.name
            && p.type === PNodeType.Function
          ) {
            node.update(PNode.funcFromGraph(unsave.value))
          }
        }
      }
    }
    // 应用修改
    props.target.params = unsave.value.params
    props.target.returns = unsave.value.returns
    props.target.name = unsave.value.name
    props.target.title = unsave.value.name
    props.target.fixProcess()
  }
  // 干脆就没传参数（新建变量）
  else {
    const g = new Graph(unsave.value.name, unsave.value.name, true)
    g.params = unsave.value.params
    g.returns = unsave.value.returns
    g.fixProcess()
  }

  emits('update:modelValue', false)
  emits('confirm')
}

const title = computed(() => {
  return props.target ? '修改函数声明' : '创建函数'
})

function addParam() {
  const name = uniqueNaming('参数', unsave.value.params.map(x => x.name))
  unsave.value.params.push(PSlot.InData(name, name, tNum))
}

function addReturn() {
  const name = uniqueNaming('返回值', unsave.value.returns.map(x => x.name))
  unsave.value.returns.push(PSlot.OutData(name, name, tNum))
}

function deleteParam(slot: PSlot) {
  lodash.remove(unsave.value.params, x => x === slot)
}

function deleteReturn(slot: PSlot) {
  lodash.remove(unsave.value.returns, x => x === slot)
}

function isOptional(pslot: PSlot) {
  return pslot.defaultValue !== undefined
}

function changeOptional(pslot: PSlot, value: boolean) {
  // console.log(`change to ${value}`);
  
  if (value) {
    pslot.defaultValue = pslot.dataType?.default
  }
  else {
    pslot.defaultValue = undefined
  }
}
</script>